#include<pthread.h>
#include<arch/xchg.h>
#include<sys/proc.h>
#include<stdio.h>
#include<errno.h>

#define __SPIN_COUNT 10

int pthread_spin_init(pthread_spinlock_t *lock,int pshared)
{
    if(!lock)
        return EINVAL;
    atomic_set(&lock->count,0);
    lock->pshared=pshared;
    return 0;
}

int pthread_spin_destroy(pthread_spinlock_t *lock)
{
    if(!lock)
        return EINVAL;
    lock->pshared=0;
    //whild the spin is using,return EBUSY 
    if(atomic_get(&lock->count))
        return EBUSY;
    atomic_set(&lock->count,0);
    return 0;
}

int pthread_spin_lock(pthread_spinlock_t *lock)
{
    if(!lock)
        return EINVAL;
    int i;
    while(1)
    {
        for(i=0;i<__SPIN_COUNT;i++) 
        {
            if(!pthread_spin_trylock(lock))
                return 0;
        }
        sched_yeild();
    }
    return 0;
}

int pthread_spin_trylock(pthread_spinlock_t *lock)
{
    uint32_t oldval;

    if(!lock)
        return EINVAL;
    oldval=atomic_xchg(&lock->count,1);
    if(oldval!=1)
        return 0;
    return EBUSY;
}

int pthread_spin_unlock(pthread_spinlock_t *lock)
{
    if(!lock)
        return EINVAL;
    atomic_dec(&lock->count);
    return 0;
}

int pthread_spin_is_locked(pthread_spinlock_t *lock)
{
    if(!lock)
        return EINVAL;
    return atomic_get(&lock->count);
}